from django.http import FileResponse
import os
import time
from myBlog import settings
from django.core.mail import send_mail,send_mass_mail
from django.http.response import HttpResponseRedirect
from django.urls.conf import path
from index.forms import FileForm
from index.models import FileModel
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from django.core.cache import cache
from index.models import Book,Article
from django.views.decorators.cache import cache_page
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.views.generic import DetailView
# Create your views here.


def index(request):
    return HttpResponse("<html><body><a href='/'>Hello World -- DjangoWeb</a></body></html>  Hello, World. You're at the myBlog index.")

# 增加一个新的对象，用于向模板提交数据
# 模板变量语法：
# view：｛"HTML变量名" : "views变量名"｝
# HTML：｛｛变量名｝｝
# 模板过滤器语法：
# 模板过滤器可以在变量被显示前修改它，过滤器使用管道字符  {{ 变量名 | 过滤器：可选参数 }}
# 过滤器 default 为变量提供一个默认值，如果 views 传的变量的布尔值是 false，则使用指定的默认值。{{ 变量名 | default：默认值 }}
# 以下值为 false：0  0.0  False  0j  ""  []  ()  set()  {}  None
# length  返回对象的长度，适用于字符串和列表。字典返回的是键值对的数量，集合返回的是去重后的长度。

# if/else 支持嵌套。{% if %} 标签接受 and ， or 或者 not 关键字来对多个变量做判断 ，或者对变量取反（ not )


def template(request):
    context = {}
    testValue = 'Hello world Django -- Template.'
    views_name = 'template 模板标签'
    views_list = ['template', 'index', 'TEST']
    view_dict = {'name': 'Daniel', 'age': 12}
    view_str = "<a href='https://www.baidu.com'>百度一下</a>"
    view_num = 99
    username = request.COOKIES.get('username')  # cookie中读取
    context = {'username': username, 'testValue': testValue, 'name': views_name,
               'list': views_list, 'dict': view_dict, 'str': view_str, 'num': view_num}
    result = render(request, 'template.html', context)
    return result
    # 这里使用 render 来替代之前使用的 HttpResponse。render 还使用了一个字典 context 作为参数。context 字典中元素的键值 testValue 对应了模板中的变量 {{ testValue }}。


def cookie_set_get(request):
    # 以下三条需要分步查看
    # 1.设置cookie：response = HttpResponse(...) 或 response ＝ render(request, ...)
    # response.set_cookie(key,value)  给cookie签名：response.set_signed_cookie(key,value,salt='加密盐',...)
    response = HttpResponse('<p>cookie,查看响应报文头</p>')
    response.set_cookie('h1', 'Daniel')

    # # 2.读取cookie：response.COOKIES.get(key)、response.COOKIES[key]，普通cookie是明文传输的，可以直接在客户端直接打开，所以需要加盐，解盐之后才能查看
    # # response.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)，default: 默认值、salt: 加密盐、max_age: 后台控制过期时间
    # response = HttpResponse('读取cookie,数据如下：<br>')
    # if 'h1' in request.COOKIES:
    #     response.write('<p>'+request.COOKIES['h1']+'</p>')

    # # 3.删除cookie：response.delete_cookie(key)
    # response = HttpResponse('删除cookie')
    # response.delete_cookie('h1')
    return response


def login(request):
    print('登录1', request.method)
    if request.method == 'POST':
        user = request.POST.get('username')
        pwd = request.POST.get('pwd')
        if user == 'root' and pwd == '123456':
            red = redirect('/template/')  # 登录成功，则重定向到template
            red.set_cookie('username', user)  # 将用户名插入cookie(设置cookie)
            return red
        else:
            return render(request, 'login.html')
    elif request.method == 'GET':
        user = request.GET.get('username')
        pwd = request.GET.get('pwd')
        if user == 'root' and pwd == '123456':
            red = redirect('/template/')  # 登录成功，则重定向到template
            red.set_cookie('username', user)  # 将用户名插入cookie(设置cookie)
            return red
        else:
            return render(request, 'login.html')
    else:
        print('登录2', request.method)
        return render(request, 'login.html')


def logout(request):
    response = HttpResponse('退出成功')
    response.delete_cookie('username')
    return response


def session_set_get(request):
    # 设置Session中数据
    # request.session[key] = value
    # request.session.setdefault(key,value) # 存在则不设置
    # 帮你生成随机字符串，帮你将这个随机字符串和用户数据（加密后）和过期时间保存到了django-session表里面，帮你将这个随机字符串以sessionid：随机字符串的形式添加到cookie里面返回给浏览器,这个sessionid名字是可以改的，但是注意一个事情，django-session这个表，你不能通过orm来直接控制，因为你的models.py里面没有这个对应关系
    request.session['sessionKey'] = 'sessionValue'
    request.session.setdefault('sessionKeys', 123)

    # 取值Session中数据
    # request.session['k1']
    # request.session.get('k1',None)
    # request.session 从cookie里面将sessionid的值取出来，将django-session表里面的对应sessionid的值的那条记录中的session-data字段的数据拿出来（并解密）,get方法就取出k1 这个键对应的值
    print(request.session['sessionKey'])
    print(request.session.get('sessionKeys', None))

    # 删除Session中数据
    # del request.session['k1']     # django-session表里面同步删除
    del request.session['sessionKeys']

    # 所有 键、值、键值对
    # request.session.keys()
    # request.session.values()
    # request.session.items()
    print('all-Keys：', request.session.keys())

    # 会话session的key
    # session_key = request.session.session_key  获取sessionid的值
    session_key = request.session.session_key
    print('session_key：', session_key)

    # 将所有Session失效日期小于当前日期的数据删除，将过期的删除
    # request.session.clear_expired()
    # 检查会话session的key在数据库中是否存在
    # request.session.exists("session_key") #session_key就是那个sessionid的值
    # 删除当前会话的所有Session数据
    # request.session.delete()

    # 删除当前的会话数据并删除会话的Cookie。
    # 常用，清空所有cookie---删除session表里的这个会话的记录，这用于确保前面的会话数据不可以再次被用户的浏览器访问。例如，django.contrib.auth.logout() 函数中就会调用它。
    request.session.flush()

    # 设置会话Session和Cookie的超时时间
    # request.session.set_expiry(value)
    #     如果value是个整数，session会在些秒数后失效。
    #     如果value是个datatime或timedelta，session就会在这个时间后失效。
    #     如果value是0,用户关闭浏览器session就会失效。
    #     如果value是None,session会依赖全局session失效策略。

    return HttpResponse('session')


def logins(request):
    print('登录1=', request.method)
    if request.method == "POST":
        usernames = request.POST['username']
        pwd = request.POST['pwd']
        if usernames == 'root' and pwd == '123456':
            # 设置session内部的字典内容
            request.session['is_login'] = True
            request.session['usernames'] = 'root'
            # 登录成功就将url重定向到后台的url
            return redirect('/backend/')
    elif request.method == "GET":
        usernames = request.GET.get('username')
        pwd = request.GET.get('pwd')
        if usernames == 'root' and pwd == '123456':
            # 设置session内部的字典内容
            request.session['is_login'] = True
            request.session['usernames'] = 'root'
            # 登录成功就将url重定向到后台的url
            return redirect('/backend/')
    # 登录不成功或第一访问就停留在登录页面
    return render(request, 'logins.html')


def backend(request):
    is_login = request.session.get('is_login', False)
    if is_login:
        cookie_content = request.COOKIES
        session_content = request.session
        usernames = request.session['usernames']  # session中读取
        return render(request, 'backend.html', {'cookie_content': cookie_content, 'session_content': session_content, 'usernames': usernames, })
    else:
        return redirect('/logins/')


def logouts(request):
    try:
        del request.session['is_login']
    except KeyError:
        pass
    return redirect('/logins/')


# 文件系统缓存：单独视图缓存方式一
# 给要缓存的页面函数加上装饰器，这个函数的执行结果就会被缓存到文件里，括号里的内容60秒*5  也就是5分钟。
# 备注：我们在settings.py 通过TIMEOUT设置了一个超时时间，在views.py里通过装饰器@cache_page(60 * 5)也设置了一个超时时间。
# 可以这样理解，settings.py函数里的超时时间是一个全局默认的超时时间。如果我们在views.py里给函数设置了@cache_page(60 * 5)，
# 那么这个函数的超时时间就是5分钟。如果我们没有指定缓存时间的话，就按settings.py设置的默认值超时。
@cache_page(10)  # 指定缓存时间为10秒(默认15*60)
def cacheFile(request):
    now = time.strftime('%Y-%m-%d %H:%M:%S')
    return HttpResponse(now)


# 文件系统缓存：单独视图缓存方式二（装饰器的另外一种写法）
def cacheFile1(request):
    now = time.strftime('%Y-%m-%d %H:%M:%S')
    return HttpResponse(now)


# 数据库缓存
@cache_page(5)
def book(request):
    t = time.strftime('%Y-%m-%d %H:%M:%S')
    bookList = Book.objects.all()
    return render(request, 'book.html', locals())


# redis缓存
def redis_cache(request):
    # 常规命令 add 只有在key不存在的时候 才能设置成功,返回值：True or None
    # cache.add('key', 'value') #如果key已经存在,则此次赋值失效
    # 常规命令 get_or_set 如果未获取到数据 则执行set操作,返回值：key的值
    # cache.get_or_set('key', 'value', 10)
    # 常规命令 get_many() set_many()
    # >>> cache.set_many({'a': 1, 'b': 2, 'c': 3})
    # >>> cache.get_many(['a', 'b', 'c'])
    # {'a': 1, 'b': 2, 'c': 3}
    # 常规命令 delete，返回值：成功删除 1 ，删除失败0
    # cache.delete('key')
    # 常规命令 delete_many，返回值：成功删除的数据条数
    # cache.delete_many(['a', 'b', 'c'])
    # 存放token，可以直接设置过期时间，300为缓存存储时间
    cache.set('token', 'header.payload.signature', 300)
    # 取出token，cache.get(key,default值) 如果没有取到返回默认值
    token = cache.get('token')
    return HttpResponse(token)


# 分页显示
def getPage(request):
    t = time.strftime('%Y-%m-%d %H:%M:%S')
    # 数据切片分页
    # http://127.0.0.1:8000/getPage/    默认每页显示5条数据，显示第一页
    # http://127.0.0.1:8000/getPage/?page_num=3     传递单个参数，另一个参数用默认值，显示第3页
    # http://127.0.0.1:8000/getPage/?page_num=3&page_record=3   传递两个参数，同时指定每页显示数目和显示的页码
    page_num = int(request.GET.get('page_num', 1))
    page_record = int(request.GET.get('page_record', 5))
    bookInfo = Book.objects.all()
    bookList = bookInfo[page_record * (page_num-1):page_record*page_num]
    context = {"t": t, "bookList": bookList}
    return render(request, 'book.html', context)


# Django Pagination 实现简单分页
def byPaginator(request):
    # 获取全部数据
    bookInfo = Book.objects.all()
    # 进行分页，每页 5 条，少于2条合并到上一页
    paginator = Paginator(bookInfo, 5, 2)
    # 获取用户请求页的页码。我们给页码设置的 URL 类似于 http://127.0.0.1:8000/?page=2。其中 ? 号后面的 page=2 表示用户请求的页码数
    page = request.GET.get('page')
    try:
        bookInfo = paginator.page(page)  # 尝试获取用户请求页的数据
    except PageNotAnInteger:
        # 用户请求的 URL 中，page 的值可能不一定是整数，将第一页的数据返回给用户。
        bookInfo = paginator.page(1)
    except EmptyPage:
        bookInfo = paginator.page(paginator.num_pages)  # 返回最后一页的数据给用户
    return render(request, 'paginator.html', context={"bookInfo": bookInfo})


# 上传文件
def upload(request):
    form = FileForm(request.POST, request.FILES)
    if form.is_valid():
        # 选择的文件
        files = request.FILES.getlist('file')
        pathFile = os.path.join(os.getcwd(),'upload')
        # pathFile1 = './upload'
        # 遍历写入到数据库中
        for file in files:
            # 写到数据库中
            file_model = FileModel(name=file.name, path=os.path.join(pathFile, file.name))
            # file_model = FileModel(name=file.name, path=os.path.join(pathFile1, file.name))
            file_model.save()
            # 写到服务器中
            destination = open(os.path.join(pathFile, file.name), 'wb+')
            # destination = open(os.path.join(pathFile1, file.name), 'wb+')
            for chunk in file.chunks():
                destination.write(chunk)
            destination.close()
        return HttpResponse('上传成功 <a href="http://127.0.0.1:8000/fileList/">文件列表</a>')
    else:
        form = FileForm()
    return render(request, 'upload.html', {"form": form})


# 文件列表
def fileList(request):
    fileList = FileModel.objects.all()
    return render(request, 'fileList.html', locals())


# 删除文件
def delete(request):
    id = request.GET.get('id')
    fileList = FileModel.objects.get(id=id)
    fileList.delete()
    print(id,"删除成功")
    return HttpResponseRedirect("/fileList")


# 下载文件
def download(request):
    id = request.GET.get('id')
    file_result = FileModel.objects.filter(id=id)
    print(file_result)
    # 如果文件存在，就下载文件
    if file_result:
        file = list(file_result)[0]
        # 文件名称及路径
        name = file.name
        path = file.path
        # 读取文件
        file = open(path, 'rb')
        response = FileResponse(file)
        response['Content-Type']="application/octet-stream"
        response['Content-Disposition'] = 'attachment;filename="%s"' % name
        return response
    else:
        return HttpResponse('文件不存在!')


# 发邮件
def toSendMail(request):
    return render(request,'sendMail.html')


def sendMail(request):
    if request.method == 'GET':
        subject = request.GET.get('subject')   # 邮件主题
        message = request.GET.get('message')    # 邮件内容
        from_email = settings.EMAIL_HOST_USER   # 发件人
        recipient_list = request.GET.get('recipient_list')  # 邮件接收者列表
        # fail_silentl运行异常的时候是否报错，默认为True不报错
        recipient_list = settings.EMAIL_TO_USER_LIST
        result = send_mail(subject, message, from_email,recipient_list, fail_silently=False)
        print(recipient_list)
        if result == 1:
            return HttpResponse('邮件发送成功')
        else:
            return HttpResponse('邮件发送失败')
    else:
        return HttpResponse('重试')
        

def sendManyMail(request):
    message1 = ('Subject here', 'Here is the message', 'from@example.com', ['first@example.com', 'other@example.com'])
    message2 = ('Another Subject', 'Here is another message', 'from@example.com', ['second@test.com'])
    #接收元组作为参数
    result = send_mass_mail((message1, message2), fail_silently=False) # fail_silentl运行异常的时候是否报错，默认为True不报错
    if result == 1:
        return HttpResponse('邮件发送成功')
    else:
        return HttpResponse('邮件发送失败')


# ckeditor富文本编辑器
class PostDetailView(DetailView):
    model = Article
    template_name = 'post_detail.html'